﻿using System;
using System.Collections.Generic;
using System.Linq;
using Loki.Game;
using Loki.Game.GameData;
using Loki.Game.Inventory;
using Loki.Game.Objects;
using Loki.TreeSharp;
using Loki.Utilities;
using Action = Loki.TreeSharp.Action;

namespace toNyxPhysRanger
{
    public class FlasksHelper
    {

        // Me Init
        private static Player Me { get { return LokiPoe.ObjectManager.Me; } }
        private static readonly IEnumerable<InventoryItem> Inv = LokiPoe.PlayerInventory.Flasks.Items;

        public static readonly WaitTimer FlaskCd = new WaitTimer(TimeSpan.FromSeconds(0.5));

        #region FlasksInit

        public static IEnumerable<InventoryItem> LifeFlasks
        {
            get
            {
                return from item in Inv
                       let flask = item.Flask
                       where flask != null /*&& flask.Rarity != Rarity.Unique*/ && flask.HealthRecover > 0 && flask.CanUse
                       orderby flask.IsInstantRecovery ? flask.HealthRecover : flask.HealthRecoveredPerSecond descending
                       select item;
            }
        }

        public static IEnumerable<InventoryItem> ManaFlasks
        {
            get
            {
                return from item in Inv
                       let flask = item.Flask
                       where flask != null /*&& flask.Rarity != Rarity.Unique*/ && flask.ManaRecover > 0 && flask.CanUse
                       orderby flask.IsInstantRecovery ? flask.ManaRecover : flask.ManaRecoveredPerSecond descending
                       select item;
            }
        }

        public static IEnumerable<InventoryItem> GraniteFlasks
        {
            get
            {
                return from item in Inv
                       let flask = item.Flask
                       where flask != null && item.Name == "Granite Flask" && flask.CanUse
                       select item;
            }
        }

        public static IEnumerable<InventoryItem> JadeFlasks
        {
            get
            {
                return from item in Inv
                       let flask = item.Flask
                       where flask != null && item.Name == "Jade Flask" && flask.CanUse
                       select item;
            }
        }

        public static IEnumerable<InventoryItem> RubyFlasks
        {
            get
            {
                return from item in Inv
                        let flask = item.Flask
                        where flask != null && item.Name == "Ruby Flask" && flask.CanUse
                        select item;
            }
        }
        public static IEnumerable<InventoryItem> DiamondFlasks
        {
            get
            {
                return from item in Inv
                        let flask = item.Flask
                        where flask != null && item.Name == "Diamond Flask" && flask.CanUse
                        select item;
            }
        }

        public static IEnumerable<InventoryItem> QuicksilverFlasks
        {
            get
            {
                //InternalName: flask_utility_sprint, BuffType: 24, CasterId: 13848, OwnerId: 0, TimeLeft: 00:00:05.0710000, Charges: 1, Description: You have greatly increased Movement Speed
                return from item in Inv
                        let flask = item.Flask
                        where flask != null && item.Name == "Quicksilver Flask" && flask.CanUse
                        select item;
            }
        }

        private IEnumerable<InventoryItem> BleedingFlasks
        {
            get
            {

                return from item in Inv
                        let flask = item.Flask
                        where flask != null && item.Item.ExplicitStats.ContainsKey(StatType.LocalFlaskRemoveBleedingOnUse) && flask.CanUse
                        select item;
            }
        }

        public static IEnumerable<InventoryItem> ShockFlasks
        {
            get
            {
                return from item in Inv
                        let flask = item.Flask
                        where flask != null && item.Item.ExplicitStats.ContainsKey(StatType.LocalFlaskRemoveShockOnUse) && flask.CanUse
                        select item;
            }
        }

        public static IEnumerable<InventoryItem> BurningFlasks
        {
            get
            {
                return from item in Inv
                        let flask = item.Flask
                        where flask != null && item.Item.ExplicitStats.ContainsKey(StatType.LocalFlaskDispelsBurning) && flask.CanUse
                        select item;
            }
        }

        public static IEnumerable<InventoryItem> FrozenFlasks
        {
            get
            {
                return from item in Inv
                        let flask = item.Flask
                        where flask != null && item.Item.ExplicitStats.ContainsKey(StatType.LocalFlaskDispelsFreezeAndChill) && flask.CanUse
                        select item;
            }
        }

        public static IEnumerable<InventoryItem> DivinationDistillate
        {
            get
            {
                return from item in Inv
                        let flask = item.Flask
                        where flask != null && item.FullName == "Divination Distillate" && flask.CanUse
                        select item;
            }
        }

        #endregion
        
        #region Flasks Methods

        public static PrioritySelector GetFullFlaskLogic()
        {
            return new PrioritySelector(

                // LifeFlask Logic
                LifeFlaskLogic(),

                // ManaFlask Logic
                ManaFlaskLogic(),

                // GraniteFlask Handler
                GraniteFlaskLogic(),

                // JadeFlask Handler
                JadeFlaskLogic());

            // RubyFlask Handler
            //RubyFlaskLogic(),

            // DiamondFlask Handler
            //DiamondFlaskLogic()),

            // BleedingFlask Handler
            //BleedingFlaskLogic(),

            // ShockFlask Handler
            //ShockFlaskLogic());

            // BurningFlask Handler
            //BurningFlaskLogic(),

            // FrozenFlask Handler
            //FrozenFlaskLogic());

            // DivinationFlask Handler
            //DivinationFlaskLogic(),

        }

        #endregion

        #region Individual Flasks Logic

        public static Decorator LifeFlaskLogic()
        {
            return new Decorator(ret =>
                                 FlaskCd.IsFinished &&
                                 Me.HealthPercent < toNyxPhysRanger.MyFlasksSettings.LifeFlaskThreshold &&
                                 LifeFlasks.Count() != 0 &&
                                 !Me.HasAura("flask_effect_life"),

                                 new Action(ret =>
                                 {
                                     LifeFlasks.First().Use();
                                     FlaskCd.Reset();
                                 }));
        }

        public static Decorator ManaFlaskLogic()
        {
            return new Decorator(ret =>
                                 FlaskCd.IsFinished && Me.ManaPercent < toNyxPhysRanger.MyFlasksSettings.ManaFlaskThreshold &&
                                 ManaFlasks.Count() != 0 &&
                                 !Me.HasAura("flask_effect_mana"),

                                 new Action(ret =>
                                 {
                                     ManaFlasks.First().Use();
                                     FlaskCd.Reset();
                                 }));
        }

        private static Composite GraniteFlaskLogic()
        {
            return new Decorator(ret =>
                                 toNyxPhysRanger.MyFlasksSettings.UseGraniteFlask && // Check if we're gonna use it
                                 FlaskCd.IsFinished &&
                                 Me.HealthPercent < toNyxPhysRanger.MyFlasksSettings.GraniteFlaskThreshold &&
                                 GraniteFlasks.Count() != 0 &&
                                 !Me.HasAura("flask_effect_granite"),

                                 new Action(ret =>
                                 {
                                     GraniteFlasks.First().Use();
                                     FlaskCd.Reset();
                                 }));
        }

        private static Composite JadeFlaskLogic()
        {
            return new Decorator(ret =>
                          toNyxPhysRanger.MyFlasksSettings.UseJadeFlask && // Check if we're gonna use it
                          FlaskCd.IsFinished &&
                          Me.HealthPercent < toNyxPhysRanger.MyFlasksSettings.JadeFlaskThreshold &&
                          JadeFlasks.Count() != 0 &&
                          !Me.HasAura("flask_effect_jade"),

                          new Action(ret =>
                          {
                              JadeFlasks.First().Use();
                              FlaskCd.Reset();
                          }));
        }

        // TODO
        private Composite RubyFlaskLogic()
        {
            return null;
        }

        // TODO
        private Composite DiamondFlaskLogic()
        {
            return null;
        }

        // TODO
        private Composite BleedingFlaskLogic()
        {
            return null;
        }

        // TODO
        private Composite ShockFlaskLogic()
        {
            return null;
        }

        // TODO
        private Composite BurningFlaskLogic()
        {
            return null;
        }

        // TODO
        private Composite FrozenFlaskLogic()
        {
            return null;
        }

        // TODO
        private Composite DivinationFlaskLogic()
        {
            return null;
        }

        #endregion

    }
}
